#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/acpi.h>
#include <asm/uaccess.h>
#include <linux/kernel.h>

MODULE_LICENSE ("GPL");

#define IO_PAD	 0x32b3015c
#define GPIO_DDR 0x28039004
#define GPIO_DR  0x28039000

static int major;
static struct class *led_cls;

int led_open (struct inode *inode, struct file *filp)
{
	printk (KERN_ALERT "%s - %d - %s\n", __FILE__, __LINE__, __func__);
	return 0;
}

int led_close (struct inode *inode, struct file *filp)
{
	printk (KERN_ALERT "%s - %d - %s\n", __FILE__, __LINE__, __func__);
	return 0;
}

ssize_t led_read (struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
	printk (KERN_ALERT "%s - %d - %s", __FILE__, __LINE__, __func__);
	return 0;
}

ssize_t led_write (struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
	printk (KERN_ALERT "%s - %d - %s", __FILE__, __LINE__, __func__);
	return 0;
}

static struct file_operations led_fops = 
{
	.owner = THIS_MODULE,
	.open = led_open,
	.release = led_close,
	.read = led_read,
	.write = led_write,
};

int __init led_drv_init (void)
{
	void __iomem *vaddr;

	major = register_chrdev (0, "dev_led", &led_fops);
	//设备文件的自动创建
	//led_cls 就是设备类的句柄
	led_cls = class_create (THIS_MODULE, "led"); 
	device_create (led_cls, NULL, MKDEV(major, 0), NULL, "led_gpio5_0");

	//gpio_mode: pull up, driver level 4, function 6
	vaddr = ioremap (IO_PAD, 4);
	writel (0x246, vaddr);
	
	//direction: output 
	vaddr = ioremap (GPIO_DDR, 4);
	writel (readl(vaddr) | 0x00000001, vaddr);

	//output high
	vaddr = ioremap (GPIO_DR, 4);
	writel (readl(vaddr) | 0x00000001, vaddr);

	return 0;
}
void __exit led_drv_exit (void)
{
	void __iomem * vaddr;
	
	vaddr = ioremap (GPIO_DR, 4);
	writel (0xfffffffe & readl (vaddr), vaddr);
	
	//解除映射
	iounmap (vaddr);
	//注销设备文件
	device_destroy (led_cls, MKDEV(major, 0));
	//注销设备类
	class_destroy (led_cls);
	//注销设备号
	unregister_chrdev (major, "dev_led");

	return ;
}
module_init (led_drv_init);
module_exit (led_drv_exit);
